package com.shigen.demo.atguigu;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * ABA问题的解决
 *
 * @author shigenfu
 * @date 2022/5/21 10:12 下午
 */
public class ABADemo {

  static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
  static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

  public static void main(String[] args) {
    new Thread(() -> {
      atomicReference.compareAndSet(100, 101);
      atomicReference.compareAndSet(101, 100);
    }, "t1").start();

    new Thread(() -> {
      try {
        TimeUnit.SECONDS.sleep(1);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }

      System.out.println(atomicReference.compareAndSet(100, 2021) + " " + atomicReference.get());

    }, "t2").start();


    // ==========================
    System.out.println("ABA问题的解决：");


    new Thread(() -> {
      int stamp = atomicStampedReference.getStamp();
      System.out.println(Thread.currentThread().getName() + " version: " + stamp + " " + atomicStampedReference.getReference());
      boolean compareAndSet = atomicStampedReference.compareAndSet(100, 101, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
      System.out.println(compareAndSet + "   version-2:" + atomicStampedReference.getStamp() + " " + atomicStampedReference.getReference());
      boolean compareAndSet1 = atomicStampedReference.compareAndSet(101, 100, atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
      System.out.println(compareAndSet1 + "   version-3:" + atomicStampedReference.getStamp() + " "+ atomicStampedReference.getReference());
      try {
        TimeUnit.SECONDS.sleep(3);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }, "t3").start();

    new Thread(() -> {
      int stamp = atomicStampedReference.getStamp();
      System.out.println(Thread.currentThread().getName() + " version: " + stamp);

      try {
        TimeUnit.SECONDS.sleep(1);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      boolean compareAndSet2 = atomicStampedReference.compareAndSet(100, 101, stamp, atomicStampedReference.getStamp() + 1);
      System.out.println(compareAndSet2 + "   version-4:" + atomicStampedReference.getStamp());
      System.out.println(atomicStampedReference.getReference());
    }, "t4").start();

  }

}
